package simultaneously.pattern.producer;

import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * notifyAll(),wait()实现
 */
class Warehouse3{
    private final Queue<Integer> sharedQueue;
    private final int max_capability;
    private int pid = 0;
    private Lock lock = new ReentrantLock();
    private Condition fullCondition = lock.newCondition();
    private Condition emptyCondition = lock.newCondition();
    public Warehouse3(int capability){
        sharedQueue = new PriorityQueue<Integer>(capability);
        this.max_capability = capability;
    }
    public void produce(){
        lock.lock();
        while(sharedQueue.size() == max_capability){
            try{
                System.out.println("生产：产能过剩！等待消费！");
                fullCondition.await();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        System.out.println("生产：制作产品"+ ++pid);
        sharedQueue.offer(pid);
        emptyCondition.signalAll();
        lock.unlock();
    }
    public void custom(){
        lock.lock();
        while(sharedQueue.isEmpty()){
            try{
                System.out.println("消费：无产品！等待生产！");
                emptyCondition.await();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        System.out.println("消费：消费产品"+sharedQueue.poll());
        fullCondition.signalAll();
        lock.unlock();
    }
}

class Producer3 implements Runnable{
    private final Warehouse3 warehouse;
    public Producer3(Warehouse3 warehouse){
        this.warehouse  = warehouse;
    }
    public void run(){
        while (true){
            warehouse.produce();
        }
    }
}

class Customer3 implements Runnable{
    private final Warehouse3 warehouse;
    public Customer3(Warehouse3 warehouse){
        this.warehouse = warehouse;
    }
    public void run(){
        while (true){
            warehouse.custom();
        }
    }
}

public class ProducerCustomerPattern3 {
    public static void main(String[] args){
        Warehouse3 warehouse = new Warehouse3(10);
        Thread p1 = new Thread(new Producer3(warehouse));
        Thread p3 = new Thread(new Producer3(warehouse));
        Thread c1 = new Thread(new Customer3(warehouse));
        Thread c3 = new Thread(new Customer3(warehouse));
        p1.start();
        p3.start();
        c1.start();
        c3.start();
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.exit(0);
            }
        },10);
    }
}
